package datavalidation

import (
	"errors"
	"fmt"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/gvalid"
	"math"
	"reflect"
)

var DataValidationtest = new(datavalidationtestApi)

type datavalidationtestApi struct {
}

func (p *datavalidationtestApi) Test1() {
	rule := "length:6,16" //长度6到16位
	if e := gvalid.Check("123456", rule, nil); e != nil {
		fmt.Println(e.String())
	}
	if e := gvalid.Check("1234", rule, nil); e != nil {
		fmt.Println(e.String())
	}
}

func (p *datavalidationtestApi) Test2() {
	rule := "integer|between:6,16" //整型而且长度6到16位
	msgs := "请输入整数|参数长度6到16位"
	if e := gvalid.Check(5.66, rule, msgs); e != nil {
		fmt.Println(e.Map())
	}
}

func (p *datavalidationtestApi) Test3() {
	rule := "url|min-length:11" //url并且最少11位
	msgs := map[string]string{
		"url":        "请输入正确的URL地址",
		"min-length": "地址长度至少:min位",
	}
	if e := gvalid.Check("http://www.baidu.com", rule, msgs); e != nil {
		fmt.Println(e.Map())
	}
}

func (p *datavalidationtestApi) Test4() {
	rule := `regex:\d{6,}|\D{6,}|max-length:16` //至少6个数字,而且长度不能超过16位
	if e := gvalid.Check("123456", rule, nil); e != nil {
		fmt.Println(e.Map())
	}
	if e := gvalid.Check("abced6", rule, nil); e != nil {
		fmt.Println(e.Map())
	}
}

func (p *datavalidationtestApi) Test5() {
	params := map[string]interface{}{
		"passport":  "",
		"password":  "123456",
		"password2": "1234567",
	}
	/*
		rules:=map[string]string{
			"passport":"required|length:6,16",
			"password":"required|length:6,16|same:password2",
			"password2":"required|length:6,16",
		}
		msgs:=map[string]interface{}{//无序
			"passport":"账号不能为空|长度在:min和:max之间",
			"password":map[string]string{
				"required":"密码不能为空",
				"same":"两次密码输入不相等",
			},
		}
	*/
	rules := []string{ //有序
		"passport@required|length:6,16#账号不能为空|账号长度应当在:min到:max之间",
		"password@required|length:6,16|same:password2#密码不能为空|密码长度应当在:min到:max之间|两次密码输入不相等",
		"password2@required|length:6,16#",
	}
	//if e:=gvalid.CheckMap(params,rules,msgs);e!=nil{
	if e := gvalid.CheckMap(params, rules); e != nil {
		fmt.Println(e.Map())
		fmt.Println(e.FirstItem())
		fmt.Println(e.FirstString())
	}
}
func (p *datavalidationtestApi) Test6() {
	type Object struct {
		Name string
		Age  int
	}
	rules := map[string]string{
		"Name": "required|length:6,16",
		"Age":  "between:18,30",
	}
	msgs := map[string]interface{}{
		"Name": map[string]string{
			"required": "名称不能为空",
			"length":   "名称长度为:min到:max个字符",
		},
		"Age": "年龄为18到30周岁",
	}
	obj := Object{Name: "john"}
	// 也可以是指针
	// obj := &Object{Name : "john"}
	if e := gvalid.CheckStruct(obj, rules, msgs); e != nil {
		g.Dump(e.Maps())
	}
}

func (p *datavalidationtestApi) Test7() {
	type User struct {
		Uid   int    `v:"uid      @integer|min:1"`
		Name  string `v:"name     @required|length:6,30#请输入用户名称|用户名称长度非法"`
		Pass1 string `v:"password1@required|password3"`
		Pass2 string `v:"password2@required|password3|same:password1#||两次密码不一致，请重新输入"`
	}
	user := &User{
		Name:  "john",
		Pass1: "Abc123!@#",
		Pass2: "123",
	}

	// 使用结构体定义的校验规则和错误提示进行校验
	if e := gvalid.CheckStruct(user, nil); e != nil {
		g.Dump(e.Maps())
	}

	// 自定义校验规则和错误提示，对定义的特定校验规则和错误提示进行覆盖
	rules := map[string]string{
		"uid": "min:6",
	}
	msgs := map[string]interface{}{
		"password2": map[string]string{
			"password3": "名称不能为空",
		},
	}
	if e := gvalid.CheckStruct(user, rules, msgs); e != nil {
		g.Dump(e.Maps())
	}
}

func (p *datavalidationtestApi) Test8() {
	type Pass struct {
		Pass1 string `valid:"password1@required|same:password2#请输入您的密码|您两次输入的密码不一致"`
		Pass2 string `valid:"password2@required|same:password1#请再次输入您的密码|您两次输入的密码不一致"`
	}
	type User struct {
		Pass
		Id   int
		Name string `valid:"name@required#请输入您的姓名"`
	}
	user := &User{
		Name: "john",
		Pass: Pass{
			Pass1: "1",
			Pass2: "2",
		},
	}
	err := gvalid.CheckStruct(user, nil)
	g.Dump(err.Maps())
}

func (p *datavalidationtestApi) Test9() {
	registerRule := "unique-name"
	err := gvalid.RegisterRule(registerRule, func(rule string, value interface{}, message string, params map[string]interface{}) error {
		var (
			id   = gconv.Int(params["Id"])
			name = gconv.String(value)
		)
		n, err := g.Table("user").Where("id != ? and name = ?", id, name).Count()
		if err != nil {
			return err
		}
		if n > 0 {
			return errors.New(message)
		}
		return nil
	})
	type User struct {
		Id   int
		Name string `v:"required|unique-name # 请输入用户名称|用户名称已被占用"`
		Pass string `v:"required|length:6,18"`
	}
	user := &User{
		Id:   1,
		Name: "john",
		Pass: "123456",
	}
	err = gvalid.CheckStruct(user, nil)
	fmt.Println(err.Error())
}

func (p *datavalidationtestApi) Test10() {
	registerRule := "required"
	gvalid.RegisterRule(registerRule, func(rule string, value interface{}, message string, params map[string]interface{}) error {
		reflectValue := reflect.ValueOf(value)
		if reflectValue.Kind() == reflect.Ptr {
			reflectValue = reflectValue.Elem()
		}
		isEmpty := false
		switch reflectValue.Kind() {
		case reflect.Bool:
			isEmpty = !reflectValue.Bool()
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			isEmpty = reflectValue.Int() == 0
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
			isEmpty = reflectValue.Uint() == 0
		case reflect.Float32, reflect.Float64:
			isEmpty = math.Float64bits(reflectValue.Float()) == 0
		case reflect.Complex64, reflect.Complex128:
			c := reflectValue.Complex()
			isEmpty = math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
		case reflect.String, reflect.Map, reflect.Array, reflect.Slice:
			isEmpty = reflectValue.Len() == 0
		}
		if isEmpty {
			return errors.New(message)
		}
		return nil
	})
	fmt.Println(gvalid.Check("", "required", "It's required"))
	fmt.Println(gvalid.Check([]string{}, "required", "It's required"))
	fmt.Println(gvalid.Check(map[string]int{}, "required", "It's required"))
	gvalid.DeleteRule(registerRule)
	fmt.Println("rule deleted")
	fmt.Println(gvalid.Check("", "required", "It's required"))
	fmt.Println(gvalid.Check([]string{}, "required", "It's required"))
	fmt.Println(gvalid.Check(map[string]int{}, "required", "It's required"))
}
